package com.dimples.system.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dimples.common.constant.DimplesConst;
import com.dimples.common.constant.StrPool;
import com.dimples.common.exception.DataException;
import com.dimples.common.page.metadata.Page;
import com.dimples.common.service.DimplesJwtTokenServiceImpl;
import com.dimples.common.transport.QueryRequest;
import com.dimples.common.util.HttpContextUtil;
import com.dimples.system.entity.SysDept;
import com.dimples.system.entity.SysUser;
import com.dimples.system.mapper.SysDeptMapper;
import com.dimples.system.service.SysDeptService;
import com.dimples.system.service.SysUserService;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2021/7/18
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {

    private final DimplesJwtTokenServiceImpl tokenService;
    @Resource
    private SysUserService sysUserService;

    @Override
    public Page<SysDept> findDept(SysDept sysDept, QueryRequest queryRequest) {
        Page<SysDept> page = new Page<>(queryRequest.getPageNumber(), queryRequest.getPageSize());
        page.setRecords(this.baseMapper.listDept(page, sysDept));
        return page;
    }

    @Override
    public List<Tree<Long>> findDeptTree() {
        List<SysDept> sysDepts = this.list();
        List<TreeNode<Long>> nodeList = CollUtil.newArrayList();
        for (SysDept sysDept : sysDepts) {
            TreeNode<Long> treeNode = new TreeNode<>(sysDept.getDeptId(), sysDept.getParentId(), sysDept.getDeptName(), sysDept.getSort());
            nodeList.add(treeNode);
        }

        return TreeUtil.build(nodeList, DimplesConst.DEFAULT_PARENT, new TreeNodeConfig()
                        .setIdKey("deptId")
                        .setNameKey("deptName")
                        .setWeightKey("orderName"),
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setWeight(treeNode.getWeight());
                    tree.setName(treeNode.getName());
                });
    }

    @Override
    public void saveDept(SysDept sysDept) {
        sysDept.setCreateBy(tokenService.getUsernameFromToken(HttpContextUtil.getRequest()));
        sysDept.setCreateTime(new Date());
        if (ObjectUtil.isNotEmpty(sysDept.getLeader()) && ObjectUtil.isEmpty(this.sysUserService.getById(sysDept.getLeader()))) {
            throw new DataException(StrUtil.format("负责人[ leader = {} ]不存在", sysDept.getLeader()));
        }
        this.save(sysDept);
    }

    @Override
    public void updateDept(SysDept sysDept) {
        if (ObjectUtil.isEmpty(sysDept.getDeptId())) {
            throw new DataException("deptId不能为空");
        }
        if (ObjectUtil.isEmpty(this.getById(sysDept.getDeptId()))) {
            throw new DataException(StrUtil.format("[ deptId = {} ]不存在", sysDept.getDeptId()));
        }
        this.updateById(sysDept);
    }

    @Override
    public void deleteDept(Long deptId) {
        if (CollUtil.isNotEmpty(this.sysUserService.list(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getDeptId, deptId)))) {
            throw new DataException(StrUtil.format("部门id [ deptId = {} ]已被用户引用, 删除失败", deptId));
        }
        if (CollUtil.isNotEmpty(this.list(Wrappers.lambdaQuery(SysDept.class).eq(SysDept::getParentId, deptId)))) {
            throw new DataException(StrUtil.format("部门id [ deptId = {} ]存在下属组织, 删除失败", deptId));
        }
        this.removeById(deptId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteDepts(String deptIds) {
        long[] depts = StrUtil.splitToLong(deptIds, StrPool.COMMA);
        for (long dept : depts) {
            deleteDept(dept);
        }
    }
}
